/*
 *  curl_resource.cc
 *  wonderland-project
 *
 *  Created by Ben Nolan on 20/10/08.
 *  Copyright 2008 Nolan Consulting Limited. All rights reserved.
 *
 */

#include "wonderland.h"
#include "curl_resource.h"
#include <curl/curl.h>
#include <boost/foreach.hpp>
#include <boost/filesystem/operations.hpp>
#include <OgreArchive.h>
#include <OgreArchiveManager.h>
#include <OgreMaterialManager.h>
#include <OgreTextureManager.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <stdlib.h>

namespace curl_resource{

static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream){
  int written = fwrite(ptr, size, nmemb, (FILE *)stream);
  return written;
}

}

bool test_curl(const std::string& url){

  std::string filename = Wonderland::Locations::Cache() + "body.zip";

  CURL *curl_handle;
  static const char *bodyfilename = filename.c_str();
  FILE *bodyfile;

  curl_global_init(CURL_GLOBAL_ALL);

  /* init the curl session */
  curl_handle = curl_easy_init();

  /* set URL to get */
  curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str());

  /* no progress meter please */
  curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);

  /* send all data to this function  */
  curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, curl_resource::write_data);

  if(!boost::filesystem::exists(filename)){
    /* open the files */
    bodyfile = fopen(bodyfilename,"w");
    if (bodyfile == NULL) {
      curl_easy_cleanup(curl_handle);
      return false;
    }

    /* we want the headers to this file handle */
    curl_easy_setopt(curl_handle,   CURLOPT_WRITEDATA, bodyfile);

    /* only download if modified since last download 
    // todo: replace with etags
    
    if(boost::filesystem::exists(filename)){
      boost::intmax_t written_at = boost::filesystem::last_write_time(filename);

      curl_easy_setopt(curl_handle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
      curl_easy_setopt(curl_handle, CURLOPT_TIMEVALUE, (long)written_at);
    }

    */
    
    /*
     * Notice here that if you want the actual data sent anywhere else but
     * stdout, you should consider using the CURLOPT_WRITEDATA option.  */

    std::cout << "Downloading " << url << "..." << std::endl;

    /* get it! */
    curl_easy_perform(curl_handle);

    /* close the header file */
    fclose(bodyfile);

  }
  
  std::cout << "Downloaded " << url << " to " << filename << "..." << std::endl;

  // Open archive
  Ogre::Archive *archive;
  Ogre::StringVector files;
  
  try{
    archive = Ogre::ArchiveManager::getSingleton().load(filename, "Zip");
    files = *archive->list();
  }catch(...){
    std::cout << "  [error] could not read archive" << std::endl;
  }

  // Add contents of archive to the ogre cached resources
  std::cout << "Contents of " << url << "..." << std::endl;

  BOOST_FOREACH(std::string fn, files){
    std::cout << "  * " << fn << std::endl;
    
    Ogre::DataStreamPtr content = archive->open(fn);

    // Load materials
    if(fn.find(".material")!=std::string::npos){
      try{
        Ogre::MaterialManager::getSingleton().parseScript(content, "Cache");
      }catch(...){
        std::cout << "  [error] could not process material " << fn << std::endl;
      }
    }

    // Load pngs or jpgs
    if( (fn.find(".png")!=std::string::npos) || (fn.find(".jpg")!=std::string::npos) ){
      try{
        Ogre::Image im; 
        im.load(content, fn.substr(fn.rfind('.')+1)); 

        Ogre::TextureManager::getSingleton().loadImage(fn, "Cache", im);
      }catch(...){
        std::cout << "  [error] could not load image " << fn << std::endl;
      }
    }
  }

  try{
    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(filename, "Zip", "Cache");
  }catch(...){
    Wonderland::Utility::fatalException("Problem loading mesh from the /cache/ directory");
  }

                                      
//  delete archive;
  
  /* cleanup curl stuff */
  curl_easy_cleanup(curl_handle);

  return true;
}
